import axios from "axios";
import { useCookies } from "vue3-cookies";
import { ElMessage } from "element-plus";
const { cookies } = useCookies();
const service = axios.create({
	baseURL: import.meta.env.VITE_API_BASE_URL,
	withCredentials: true,
	timeout: 600000,
});
service.interceptors.request.use((request) => {
	if (cookies.get("token")) {
		request.headers.Authorization = "Bearer " + cookies.get("token");
	}
	return request;
});
service.interceptors.response.use(
	(response) => {
		return response;
	},
	(error) => {
		if (error.response) {
			const { status, data } = error.response;
			if (data?.msg === "账号或密码错误") {
				cookies.remove("token");
				ElMessage.error("账号或密码\n错误");
			} else if (status === 401) {
				cookies.remove("token");
				window.location.href = "/login";
				ElMessage.error("登录已过期，请重新登录");
			} else if (status !== 200) {
				ElMessage.error(data?.msg || `服务器错误（${status}），请稍后重试`);
			}
		} else {
			if (error.code === "ECONNABORTED") {
				ElMessage.error("请求超时，请检查网络或稍后重试");
			} else {
				ElMessage.error("网络连接异常，请检查网络后重试");
			}
		}

		return Promise.reject(error);
	}
);
const debounce = (fn, delay = 300) => {
	let timer = null;
	return function (...args) {
		clearTimeout(timer);
		return new Promise((resolve, reject) => {
			timer = setTimeout(() => {
				try {
					const result = fn.apply(this, args);
					resolve(result);
				} catch (error) {
					reject(error);
				}
			}, delay);
		});
	};
};
const throttle = (fn, delay = 300) => {
	let lastExec = 0;
	let timer = null;
	return function (...args) {
		const now = Date.now();
		if (now - lastExec > delay) {
			lastExec = now;
			return fn.apply(this, args);
		} else if (!timer) {
			return new Promise((resolve, reject) => {
				timer = setTimeout(() => {
					try {
						const result = fn.apply(this, args);
						resolve(result);
					} catch (error) {
						reject(error);
					}
					lastExec = Date.now();
					timer = null;
				}, delay - (now - lastExec));
			});
		} else {
			return Promise.resolve(null);
		}
	};
};
const debounceCache = new Map();
const throttleCache = new Map();
const simpleHash = (str) => {
	let hash = 0;
	for (let i = 0; i < str.length; i++) {
		const char = str.charCodeAt(i);
		hash = (hash << 5) - hash + char;
		hash |= 0;
	}
	return hash.toString(36).replace(/^-/, "m");
};
const sortedStringify = (obj) => {
	if (!obj || typeof obj !== "object") return JSON.stringify(obj);
	const sortedKeys = Object.keys(obj).sort();
	const sortedObj = sortedKeys.reduce((acc, key) => {
		acc[key] = obj[key];
		return acc;
	}, {});
	return JSON.stringify(sortedObj);
};
const request = (config) => {
	const { debounce: debounceDelay, throttle: throttleDelay, url, method, data, params } = config;
	const rawKey = `${method || "get"}:${url}:${sortedStringify(data || {})}:${sortedStringify(params || {})}`;
	const cacheKey = simpleHash(rawKey);
	let finalRequest = () => service(config);
	if (debounceDelay) {
		if (!debounceCache.has(cacheKey)) {
			debounceCache.set(cacheKey, debounce(finalRequest, debounceDelay));
		}
		finalRequest = debounceCache.get(cacheKey);
	} else if (throttleDelay) {
		if (!throttleCache.has(cacheKey)) {
			throttleCache.set(cacheKey, throttle(finalRequest, throttleDelay));
		}
		finalRequest = throttleCache.get(cacheKey);
	}

	return finalRequest();
};
export default request;
